
#ifndef TRANSFERMESSAGE_H_
#define TRANSFERMESSAGE_H_

#include "ariba/ariba.h"
#include <boost/shared_ptr.hpp>

using_serialization;

typedef uint64_t omnibus_seq_num;

// XXX deprecated
//typedef uint32_t omnibus_seq_num;
//#define INVALID_SEQ_NUM 0
//#define NO_ACK false
//#define ACK true

class TransportMessage  : public ariba::Message
{
	VSERIALIZEABLE;
public:
        /** transport message types **/
        typedef enum _MESSAGE_TYPE
        {
            UNDEFINED = 0,
            CONNECTION = 1,
            CHAT = 2,
            MEET = 3,
            Transfer_Negotiation = 4,
            Transfer_Payload = 5,
            SYNC = 6,
            ACK = 7
        } MESSAGE_TYPE;

        typedef enum _MESSAGE_FLAG
        {
            MASK_TYPES = 127,
            
            ACK_REQUESTED = 128
        } MESSAGE_FLAG;


	/// Default constructor, required for automatic de-serialization
	TransportMessage();

	/// Convenient constructor for setting up a new chat message object
//	TransportMessage(MESSAGE_TYPE type, const ariba::NodeID srcNode, const string name);

	 /// Convenient constructor for setting up a new chat message object
	 TransportMessage(MESSAGE_TYPE type, uint8_t subtype);

	/// Copy constructor
//	TransportMessage(TransportMessage &other); //XXX

	/// Default destructor
	virtual ~TransportMessage();


    MESSAGE_TYPE getType();
    uint8_t getSubtype();
//    bool is_ack();
    
    void set_flag(MESSAGE_FLAG flag);
    bool has_flag(MESSAGE_FLAG flag);

    omnibus_seq_num get_seq_num() const;
    void set_seq_num(omnibus_seq_num seqNum);

    void request_ack();
    bool ack_requested();
    
private:
    /** Message type **/
    uint8_t type;
    uint8_t subtype;
    omnibus_seq_num seq_num;
    //        uint8_t ack;
};

sznBeginDefault(TransportMessage, X)
{
    // type and subtype
    X && type && subtype;
    
    // handle flags (remember, they are encoded in the type)
    //  --> sequence number
    if ( has_flag(ACK_REQUESTED) || type == ACK )
    {
        X && seq_num;
    }
    else
    {
        seq_num = 0;
    }
    
    X && Payload();
} sznEnd();

typedef boost::shared_ptr<TransportMessage> TMsgPtr;

#endif /* CHATMESSAGE_H_ */
